package com.ywx.intelligentaicodegeneration.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.ywx.intelligentaicodegeneration.constant.AppConstant;
import com.ywx.intelligentaicodegeneration.exception.BusinessException;
import com.ywx.intelligentaicodegeneration.exception.ErrorCode;
import com.ywx.intelligentaicodegeneration.exception.ThrowUtils;
import com.ywx.intelligentaicodegeneration.mode.dto.chathistory.ChatHistoryQueryRequest;
import com.ywx.intelligentaicodegeneration.mode.entity.App;
import com.ywx.intelligentaicodegeneration.mode.entity.ChatHistory;
import com.ywx.intelligentaicodegeneration.mapper.ChatHistoryMapper;
import com.ywx.intelligentaicodegeneration.mode.entity.User;
import com.ywx.intelligentaicodegeneration.mode.enums.ChatHistoryMessageTypeEnum;
import com.ywx.intelligentaicodegeneration.mode.enums.UserRoleEnum;
import com.ywx.intelligentaicodegeneration.service.AppService;
import com.ywx.intelligentaicodegeneration.service.ChatHistoryService;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 对话历史 服务层实现。
 *
 * @author <a href=\"https://gitee.com/JING5201314/aicode-gen-pro\">ywx</a>
 */
@Slf4j
@Service
public class ChatHistoryServiceImpl extends ServiceImpl<ChatHistoryMapper, ChatHistory> implements ChatHistoryService {

    @Resource
    @Lazy
    private AppService appService;

    @Override
    public boolean addChatHistory(String message, String messageType, Long appId, Long userId) {
        ThrowUtils.throwIf(appId == null || appId <= 0, ErrorCode.PARAMS_ERROR, "应用Id不能为空");
        ThrowUtils.throwIf(userId == null || userId <= 0, ErrorCode.PARAMS_ERROR, "用户Id不能为空");
        ThrowUtils.throwIf(StrUtil.isBlank(message), ErrorCode.PARAMS_ERROR, "消息不能为空");
        ThrowUtils.throwIf(StrUtil.isBlank(messageType), ErrorCode.PARAMS_ERROR, "消息类型不能为空");

        //验证消息类型是否有效
        ChatHistoryMessageTypeEnum messageTypeEnum = ChatHistoryMessageTypeEnum.getEnumByValue(messageType);
        ThrowUtils.throwIf(messageTypeEnum == null, ErrorCode.PARAMS_ERROR, "消息类型无效");

        ChatHistory chatHistory = ChatHistory.builder()
                .message(message)
                .messageType(messageType)
                .appId(appId)
                .userId(userId)
                .build();
        return this.save(chatHistory);
    }

    @Override
    public boolean deleteByAppId(Long appId) {
        ThrowUtils.throwIf(appId == null || appId <= 0, ErrorCode.PARAMS_ERROR, "应用Id不能为空");
        return this.remove(new QueryWrapper().eq("appId", appId));
    }

    @Override
    public QueryWrapper getQueryWrapper(ChatHistoryQueryRequest chatHistoryQueryRequest) {
        QueryWrapper queryWrapper = QueryWrapper.create();
        if (chatHistoryQueryRequest == null) {
            return queryWrapper;
        }
        Long id = chatHistoryQueryRequest.getId();
        String message = chatHistoryQueryRequest.getMessage();
        String messageType = chatHistoryQueryRequest.getMessageType();
        Long appId = chatHistoryQueryRequest.getAppId();
        Long userId = chatHistoryQueryRequest.getUserId();
        LocalDateTime lastCreateTime = chatHistoryQueryRequest.getLastCreateTime();
        int pageNum = chatHistoryQueryRequest.getPageNum();
        int pageSize = chatHistoryQueryRequest.getPageSize();
        String sortField = chatHistoryQueryRequest.getSortField();
        String sortOrder = chatHistoryQueryRequest.getSortOrder();
        queryWrapper.eq("id", id)
                .like("message", message)
                .eq("messageType", messageType)
                .eq("appId", appId)
                .eq("userId", userId);

        //游标查询逻辑 --只使用createTime作为游标
        if (lastCreateTime != null) {
            queryWrapper.lt("createTime", lastCreateTime);
        }
        //排序
        if (StrUtil.isBlank(sortField)) {
            //默认降序排序
            queryWrapper.orderBy("createTime", false);
        } else {
            queryWrapper.orderBy(sortField, "ascend".equals(sortOrder));
        }

        return queryWrapper;
    }

    @Override
    public Page<ChatHistory> listAppChatHistoryByPage(Long appId, Integer pageSize, LocalDateTime lastCreateTime, User loginUser) {
        //校验参数
        ThrowUtils.throwIf(appId == null || appId <= 0, ErrorCode.PARAMS_ERROR, "应用Id不能为空");
        ThrowUtils.throwIf(pageSize == null || pageSize <= 0 || pageSize > 50, ErrorCode.PARAMS_ERROR, "分页大小不能小于0或大于50");
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN_ERROR);

        //验证权限--只有应用创建者和管理员可以查看
        App app = appService.getById(appId);
        ThrowUtils.throwIf(app == null, ErrorCode.NOT_FOUND_ERROR, "应用不存在");
        if (app.getPriority().equals(AppConstant.GOOD_APP_PRIORITY)) {
            log.info("精选应用所有人可以查看对话历史");
        } else if (!app.getUserId().equals(loginUser.getId()) && !loginUser.getUserRole().equals(UserRoleEnum.ADMIN.getValue())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无访问权限");
        }

        //构建查询条件
        ChatHistoryQueryRequest chatHistoryQueryRequest = new ChatHistoryQueryRequest();
        chatHistoryQueryRequest.setAppId(appId);
        chatHistoryQueryRequest.setLastCreateTime(lastCreateTime);
        QueryWrapper queryWrapper = getQueryWrapper(chatHistoryQueryRequest);
        //查询数据
        return this.page(Page.of(1, pageSize), queryWrapper);
    }

    @Override
    public int loadChatHistoryToMemory(Long appId, MessageWindowChatMemory chatMemory, int maxCount) {

        try {
            //构造查询条件
            QueryWrapper queryWrapper = QueryWrapper.create()
                    .eq(ChatHistory::getAppId, appId)
                    .orderBy(ChatHistory::getCreateTime, false)//降序排序,获取最新的对话
                    .limit(1, maxCount);//从1开始,不获取最新的最新的用户消息

            List<ChatHistory> chatHistoryList = this.list(queryWrapper);
            if (CollUtil.isEmpty(chatHistoryList)) {
                return 0;
            }
            //反转列表,确保按时间正序(老的在前,新的在后)
            chatHistoryList = chatHistoryList.reversed();
            //按时间顺序添加到记忆中
            int loadCount = 0;
            //先清理历史缓存,防止重复加载(redis中的),chatMemory中配置了使用redis存储
            chatMemory.clear();
            for (ChatHistory chatHistory : chatHistoryList) {
                if (ChatHistoryMessageTypeEnum.USER.getValue().equals(chatHistory.getMessageType())) {
                    chatMemory.add(UserMessage.from(chatHistory.getMessage()));
                    loadCount++;
                } else if (ChatHistoryMessageTypeEnum.AI.getValue().equals(chatHistory.getMessageType())) {
                    chatMemory.add(AiMessage.from(chatHistory.getMessage()));
                    loadCount++;
                }
            }
            log.info("加载{}条对话历史到内存成功", loadCount);
            return loadCount;
        } catch (Exception e) {
            log.error("加载对话历史到内存失败", e);
            //保守策略,返回0
            return 0;
        }
    }
}
